//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <bsp.h>
#include <init.h>
#include "pic.h"
#include <timer.h>

EXTERN_C DECL_CODEINIT void CDECL InitPIC()
{
    Outl(_ICCR, _DIM);
    Outl(_ICLR, 0);
    Outl(_ICLR2, 0);

    BspMaskAllIrqs(FALSE);
}

EXTERN_C irqs_t CDECL BspGetIrqs()
{
    return (irqs_t)Inl(_ICIP) | ((irqs_t)Inl(_ICIP2) << 32);
}

INLINE void EndOfInterrupt(irq_t irq)
{
    switch (irq) {
    case PIT_Irq: EndOfPITInterrupt(); break;
#if (_TEST_TYPE == 5)    /* Test for interrupt latency performance */ \
    || (_TEST_TYPE == 6) /* Test for interrupt dispatch latency performance */

    case 29: Outl(_OSSR, _M3); break;
#endif // _TEST_TYPE == 5 || _TEST_TYPE == 6
    // TODO: add EOI codes for other devices
    }
}

STATIC irqs_t s_irqMask = 0;

#if defined(_GNUC)


#define LLCONST(n)  n##ll
#elif defined(_EVC)

#define LLCONST(n)  n

#else

#error Unknown C++ compiler

#endif // defined(_GNUC)

EXTERN_C void CDECL BspMaskIrqs(irqs_t irqs, bool_t bEnable)
{
    if (bEnable)
        s_irqMask |= irqs;
    else
        s_irqMask &= ~irqs;

    if (irqs & LLCONST(0x00000000ffffffff)) {
        Outl(_ICMR, (uint32_t)s_irqMask);
    }

    if (irqs & LLCONST(0xffffffff00000000)) {
        Outl(_ICMR2, (uint32_t)(s_irqMask >> 32));
    }
}

EXTERN_C void CDECL BspMaskAllIrqs(bool_t bEnable)
{
    s_irqMask = bEnable? LLCONST(0xffffffffff) : LLCONST(0x0000000000);

    Outl(_ICMR, (uint32_t)s_irqMask);
    Outl(_ICMR2, (uint32_t)(s_irqMask >> 32));
}

EXTERN_C void CDECL BspAcknowledgeIrq(irq_t irq)
{
    EndOfInterrupt(irq);
}
